package cn.brilliantfuture.commentry.user.impl;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;

import org.apache.log4j.Logger;

import cn.brilliantfuture.commentry.entity.CardInfo;
import cn.brilliantfuture.commentry.entity.ExpenseRecord;
import cn.brilliantfuture.commentry.entity.Purchaser;
import cn.brilliantfuture.commentry.user.UserMessageLocal;
import cn.brilliantfuture.commentry.util.CommEntryUtil;

/**
 * 
 * Title: Communication Entry
 * 
 * Author: LiTian
 * 
 * Date: 2012-3-27
 * 
 * Description:
 * 
 */
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class UserMessageImpl implements UserMessageLocal {
	
	private static Logger logger = Logger.getLogger(UserMessageImpl.class);

	@PersistenceContext(unitName = "commentry-jpa")
	EntityManager entityManager;

	@Resource
	SessionContext sessionContext;

	@SuppressWarnings("unchecked")
	public Object[] memberLogin(String username, String password) {

		logger.info("Member login method ...");
		
		List<Object[]> list = entityManager.createNativeQuery("select p.password, ci.card_number, p.realname, p.phone, p.email, p.address, li.language_name from purchaser p inner join card_info ci on p.purchaser_id = ci.purchaser_id inner join language_info li on p.language = li.language_info_id where p.deleted = 0 and ci.deleted = 0 and (p.phone = '" + username + "' or p.email = '" + username + "')").getResultList();

		if (null != list)
			if (list.size() > 0) {
				Object[] objs = list.get(0);

				password = CommEntryUtil.encodePassword(password, "SHA");

				if (objs[0].equals(password)) {
					return objs;
				} else
					return null;

			} else
				return null;
		else
			return null;
	}

	@SuppressWarnings("unchecked")
	public Object[] validMemberCode(String memberCode) {

		logger.info("Valid member code method ...");
		
		List<Object[]> list = entityManager.createNativeQuery("select p.purchaser_id, p.realname, p.phone, p.email, p.amount from purchaser p inner join card_info ci on p.purchaser_id = ci.purchaser_id where p.deleted = 0 and ci.deleted = 0 and ci.card_number = '" + memberCode + "'").getResultList();

		if (null != list && list.size() > 0){
			Object[] objs = list.get(0);
			logger.info("Member info -> " + objs);
			return objs;
		} else
			return null;
	}

	@SuppressWarnings("unchecked")
	public boolean isExistExpenseRecord(String orderCode) {
		
		logger.info("Valid member expense order code method ...");
		
		List<ExpenseRecord> list = entityManager.createQuery("select er from ExpenseRecord er where er.orderCode = '" + orderCode + "'").getResultList();

		if (null != list)
			if (list.size() > 0)
				return false;
			else
				return true;
		else
			return true;
	}

	public String memberOnlinePayment(Integer purchaserId, Integer groupId, String orderCode, double amount, String note) {

		logger.info("Member online payment method ...");
		
		UserTransaction ut = sessionContext.getUserTransaction();

		try {
			Object obj = entityManager.createNativeQuery("select amount from purchaser where deleted = 0 and purchaser_id = " + purchaserId).getSingleResult();
			
			Double balance = null;
			
			if (obj instanceof Double) {
				balance = (Double) obj;
			}
			
			if (null == balance || amount > balance.doubleValue())
				throw new Exception();
			
			ut.begin();
			
			String expenseCode = String.valueOf(System.currentTimeMillis() / 1000);

			ExpenseRecord expenseRecord = new ExpenseRecord();
			expenseRecord.setExpenseCode(expenseCode);
			expenseRecord.setType(PAYMENT_TYPE);
			expenseRecord.setPurchaserId(purchaserId);
			expenseRecord.setGroupId(groupId);
			expenseRecord.setOrderCode(orderCode);
			expenseRecord.setAmount(amount);
			expenseRecord.setExpenseBeforeBalance(balance.doubleValue());
			expenseRecord.setExpenseAfterBalance(balance.doubleValue() - amount);
			expenseRecord.setExpenseTime(new Date());
			expenseRecord.setExpenseNote(note);

			entityManager.persist(expenseRecord);

			entityManager.createNativeQuery("update purchaser set amount = " + (balance.doubleValue() - amount) + " where purchaser_id = " + purchaserId).executeUpdate();

			entityManager.flush();
			
			ut.commit();
			
			return expenseCode;
			
		} catch (Exception e) {
			
			logger.error("Member online payment fail!\n" + e.getMessage());
			
			try {
				ut.rollback();
			} catch (Exception e1) {
				logger.error("Data rollback fail!\n" + e1.getMessage());
			}

			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public Object[] validMemberInfo(String phone, String email) {
		
		logger.info("Vaild member info method ...");

		StringBuffer sql = new StringBuffer();
		
		sql.append("select p.purchaser_id, p.realname, p.phone, p.email, p.amount from purchaser p inner join card_info ci on p.purchaser_id = ci.purchaser_id where p.deleted = 0 and ci.deleted = 0");
		
		if (null != phone && !"".equals(phone) && (null == email || "".equals(email))){
			sql.append(" and p.phone = '").append(phone).append("'");
		} else if ((null == phone || "".equals(phone)) && null != email && !"".equals(email)) {
			sql.append(" and p.email = '").append(email).append("'");
		} else {
			sql.append(" and p.phone = '").append(phone).append("'");
		}

		List<Object[]> list = entityManager.createNativeQuery(sql.toString()).getResultList();

		if (list.size() > 0){
			return list.get(0);
		} else
			return null;
	}

	@SuppressWarnings("unchecked")
	public Object[] createNewMemberInfo(String realName, String email, String phone, Integer language) {

		logger.info("Create new member info method ...");
		
		UserTransaction ut = sessionContext.getUserTransaction();

		try {
			ut.begin();

			List<CardInfo> cardInfos = entityManager.createQuery("select ci from CardInfo ci where ci.deleted = 0 and ci.purchaser.purchaserId is null").setMaxResults(1).getResultList();
			CardInfo cardInfo = null;
			if (null != cardInfos && cardInfos.size() > 0) {
				cardInfo = cardInfos.get(0);
			} else {
				Object obj = entityManager.createNativeQuery("select card_number from card_info where deleted = 0 order by card_number desc").setMaxResults(1).getSingleResult();

				long number = Long.parseLong(obj.toString()) + 1;
				cardInfo = new CardInfo();
				cardInfo.setCardNumber(CommEntryUtil.getFormatStr(number + "", 9));
				cardInfo.setActive(1);
				cardInfo.setType(1);
				cardInfo.setDeleted(false);
				
				entityManager.persist(cardInfo);
			}
			
			String password = CommEntryUtil.randomPasswd();

			Purchaser purchaser = new Purchaser();
			purchaser.setName(cardInfo.getCardNumber());
			purchaser.setRealname(realName);
			purchaser.setPassword(CommEntryUtil.encodePassword(password, "SHA"));
			purchaser.setEmail(email);
			purchaser.setPhone(phone);
			purchaser.setInsertTime(new Date());
			purchaser.setAmount(0.0D);
			purchaser.setLanguage(null == language ? 1 : language);
			purchaser.setTemporary(true);
			purchaser.setDeleted(false);
			
			entityManager.persist(purchaser);
			
			cardInfo.setPurchaser(purchaser);
			entityManager.merge(cardInfo);
			entityManager.flush();
			ut.commit();

			return new Object[]{purchaser.getPurchaserId(), realName, phone, email, 0.0D};

		} catch (Exception e) {
			
			logger.error("Create new member info fail!\n" + e.getMessage());
			
			try {
				ut.rollback();
			} catch (Exception e1) {
				logger.error("Data rollback fail!\n" + e1.getMessage());
			}

			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public boolean updateMemberPasswd(String memberCode, String phone, String oldPasswd, String newPasswd) {
		
		logger.info("Update member info method ...");
		
		UserTransaction ut = sessionContext.getUserTransaction();
		
		try {
			ut.begin();
			
			List<Object[]> objs = entityManager.createNativeQuery("select p.purchaser_id, p.password from purchaser p inner join card_info ci on p.purchaser_id = ci.purchaser_id where ci.card_number = '" + memberCode + "'").getResultList();
			
			if (null != objs && objs.size() > 0){
				if (objs.get(0)[1].toString().equals(CommEntryUtil.encodePassword(oldPasswd, "SHA"))){
					entityManager.createNativeQuery("update purchaser set password = '" + CommEntryUtil.encodePassword(newPasswd, "SHA") + "' where purchaser_id = " + (Integer)objs.get(0)[0]).executeUpdate();
				} else {
					throw new Exception();
				}
			} else {
				throw new Exception();
			}
			
			ut.commit();
			return true;
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				logger.error("Data rollback fail!\n" + e1.getMessage());
			}

			return false;
		}
	}

	@SuppressWarnings("unchecked")
	public boolean memberOnlineRefund(String expenseCode, Integer purchaserId, Integer groupId, String orderCode, double amount, String note) {
		
		logger.info("Member online refund method ...");
		
		UserTransaction ut = sessionContext.getUserTransaction();

		try {
			ut.begin();
			
			List<ExpenseRecord> list = entityManager.createQuery("select er from ExpenseRecord er where er.expenseCode = '" + expenseCode + "'").getResultList();
			
			if (null == list || list.size() == 0)
				throw new Exception();
			
			ExpenseRecord expenseRecord = list.get(0);
			
			if (expenseRecord.getType() != PAYMENT_TYPE || expenseRecord.getPurchaserId() != purchaserId || expenseRecord.getGroupId() != groupId || !expenseRecord.getOrderCode().equals(orderCode) || expenseRecord.getAmount() != amount){
				throw new Exception();
			} 
			
			Object obj = entityManager.createNativeQuery("select amount from purchaser where deleted = 0 and purchaser_id = " + purchaserId).getSingleResult();
			
			Double balance = null;
			
			if (obj instanceof Double) 
				balance = (Double) obj;
			else 
				throw new Exception();
			
			expenseRecord.setType(REFUND_TYPE);
			expenseRecord.setRefundTime(new Date());
			expenseRecord.setRefundBeforeBalance(balance.doubleValue());
			expenseRecord.setRefundAfterBalance(amount + balance.doubleValue());
			expenseRecord.setRefundNote(note);
			
			entityManager.merge(expenseRecord);

			entityManager.createNativeQuery("update purchaser set amount = " + (balance.doubleValue() + amount) + " where purchaser_id = " + purchaserId).executeUpdate();

			entityManager.createNativeQuery("update order_information set is_effective = 0 where number = '" + orderCode + "' and group_id = " + groupId).executeUpdate();
			
			entityManager.flush();
			
			ut.commit();
			
			return true;
			
		} catch (Exception e) {
			
			logger.error("Member online refund fail!\n" + e.getMessage());
			
			try {
				ut.rollback();
			} catch (Exception e1) {
				logger.error("Data rollback fail!\n" + e1.getMessage());
			}

			return false;
		}

	}

	@SuppressWarnings("unchecked")
	public Double queryMemberBalance(String userId, String phone) {
		
		logger.info("Query member balance method ...");
		
		List<Object> list = entityManager.createQuery("select p.amount from Purchaser p inner join p.cardInfo ci where p.deleted = 0 and ci.deleted = 0 and ci.cardNumber = '" + userId + "' and p.phone = '" + phone + "'").getResultList();
		
		if (null != list && list.size() > 0)
			if (list.get(0) instanceof Double) {
				Double balance = (Double) list.get(0);
				return balance;
			}
		
		return null;
	}
}
